/**
 * @mainpage Úvod RaspberyPi Power Control
 * @version 1.0.0
 * @author Lukáš Michalík
 * @date 14.4.2013
 * @note
 * Poižita externí knihovna: bcm2835 http://www.open.com.au/mikem/bcm2835/index.html
 *
 * Poižity externí knihovny: wiringPi
 *
 * Zdroj knihoven wiringPi:
 *
 * git clone git://git.drogon.net/wiringPi
 *
 * https://projects.drogon.net/raspberry-pi/wiringpi/download-and-install/
 * @note
 * Tento program je určen pro aplikaci na RaspBerryPi a speciální rozšiřující moduly pro měření spotřeby elektrické energie.
 * Jedná se zejména o komunikaci po sběrnici SPI a prvkem ADE 7763. Dále jsou v kódu implementovány funkce pro spracování dat získaných z čipu
 * ADE 7763.
 * @todo
 * include <bcm2835.h> knihovna src bcm2835
 * v souboru piThread zapoznámovaná fce "int piThreadCreate (void *(*fn)(void *)) nevím co s tím
 * @todo
 * Fázová korekce strana 24 dokumentace ADE7463, funkce nebyla napsána
 */

#include <iostream>
#include "wiringPiSPI.h"
//#include "lcd.h"
//#include "stdio.h"

#include "wiringPi.h"
#include "stdio.h"
#include "stdlib.h"
#include "stdint.h"
#include "errno.h"
#include "string.h"
#include "ADE7763.hpp"
#include "src/bcm2835.h"
#include "HelloWorld.hpp"
#include "PowerBoard.hpp"
#include "SystemFunction.hpp"

/** @defgroup RaspBerryPi_Power_Control
  * @{
  */

/** @defgroup Main
  * @{
  */


using namespace std;

// LCD pins

#define	RS	21
#define	STRB 9

// commands

#define	LCD_CLEAR	0x01
#define	LCD_HOME	0x02
#define	LCD_ENTRY	0x04
#define	LCD_ON_OFF	0x08
#define	LCD_CDSHIFT	0x10
#define	LCD_FUNC	0x20
#define	LCD_CGRAM	0x40
#define	LCD_DGRAM	0x80

#define	LCD_ENTRY_SH	0x01
#define	LCD_ENTRY_ID	0x02

#define	LCD_ON_OFF_B	0x01
#define	LCD_ON_OFF_C	0x02
#define	LCD_ON_OFF_D	0x04

#define	LCD_FUNC_F	0x04
#define	LCD_FUNC_N	0x08
#define	LCD_FUNC_DL	0x10

#define	LCD_CDSHIFT_RL	0x04

#define  LCD_RS 21
#define  LCD_E  23

#define  LCD_D0 0
#define  LCD_D1 1
#define  LCD_D2 4
#define  LCD_D3 14

#define  LCD_D4 15
#define  LCD_D5 8
#define  LCD_D6 25
#define  LCD_D7 24

void setup(void);
void lcdPuts(char *string);
void lcdPutchar(uint8_t data);
void lcdPosition(int x, int y);
void putCommand(uint8_t command);
void dataByte(uint8_t data);



T_config konfigurace;



int main(void) {

	T_data zmereno;

	char strinng[1024];
	char *Pstrinng = strinng;
	int fd = 0;
	uint8_t a;
	int channel = SPI1;
	uint16_t delaytime = 550;
	int speed = SPI_ADE7763_SPEED;

	uint8_t MainBuffer[MaxBuffSize];
	uint8_t i, tmp, mem1, mem2;

	uint8_t DataNaNic = 0;
	CLEAN_POLE(MaxBuffSize, MainBuffer);
	/*tak asi nějak dělá toto
	 for (i = 1; i < MainMaxBuffSize; i++)
	 MainBuffer[i] = 0x00;*/

	//system("gpio load spi");
	SystemLoadSPI();
	Loadenv();
	mkWorkingdir();
	SystemMkfs();
	SystemMount();



	while (1)

	{

		/*
		 * SPItest3.c:
		 * LED manipulation using wiringPi SPI functions
		 * to control 6 x RGB LEDs via WS2803 chip
		 * Ramps R, G and B for each LED until all are on full.
		 * The program does 18 x 256 = 4609 writes to the chip buffer,
		 * latching the output each time, and still manages it in a couple of seconds!

		 */

		// int main (void)
		//{
		//printf (“Raspberry Pi wiringPi SPI LED test program\n”) ;
		// set output SPI channel to 0 and speed to 8MHz
		if (wiringPiSPISetup(channel, speed) < 0) {
			fprintf(stderr, "Unable to open SPI device 0: %s\n",
					strerror(errno));
			exit(1);
		}

		if (wiringPiSetup() == -1)
			exit(1);

		zmereno.rele = PowerBoardON();
		DataToFileWrite(konfigurace.mountpoit,konfigurace.fileRele,zmereno.rele);

		/*
		 printf("Starting\n");

		 digitalWrite(25, 0);
		 digitalWrite(25, 1);
		 digitalWrite(25, 0);
		 digitalWrite(24, 0);
		 digitalWrite(24, 1);
		 digitalWrite(24, 0);
		 digitalWrite(8, 0);
		 digitalWrite(8, 1);
		 digitalWrite(8, 0);
		 digitalWrite(15, 0);
		 digitalWrite(15, 1);
		 digitalWrite(15, 0);



		 printf ("Raspberry Pi LCD test program\n") ;

		 setup () ;

		 lcdPosition (0, 0) ; lcdPuts ("http://projects.") ;
		 delay (5) ;
		 lcdPosition (0, 1) ; lcdPuts ("  drogon.net/") ;
		 delay (5) ;

		 */

		//fd = lcdInit (2, 16, 8,  21,23 , 24,25,8,15,14,4,1,0) ;
//		fd = lcdInit (2, 16, 4,  21,23 , 24,25,8,15,0,0,0,0) ;
		//fd = lcdInit (2, 16, 4,  21,23 , 0,1,4,14,0,0,0,0);
		//lcdPosition (fd, 0,0) ;
		//pokus ();
		//lcdPuts (fd, "http://projects.") ;

//lcdHome     (fd) ;
//lcdClear    (fd) ;
//lcdPosition (fd, 0,0) ;
//lcdPutchar  (fd, ) ; // opravit unsigned char na uint_8
//lcdPuts     (int fd, char *string) ;
//lcdPrintf   (int fd, char *message, ...) ;

		//	lcdPosition (fd, 0, 0) ;
		//lcdPuts (fd, "http://projects.") ;
		//delay (5) ;
		//lcdPosition (fd, 0, 1) ;
		//lcdPuts ( fd,"  drogon.net/") ;
		//delay (5) ;

		//	lcdHome (handle);
		//	lcdClear (handle);
		//lcdPosition (handle, 0, 0);
		//lcdPrintf (handle, message);

		ade7763ReadAll(channel);
		//SetGainPGA27763(1);
		ade7763ReadAll(channel);
		//SetGainPGA27763(2);
		ade7763ReadAll(channel);
		//SetGainPGA27763(4);
		ade7763ReadAll(channel);
		//SetGainPGA27763(8);
		ade7763ReadAll(channel);
		//SetGainPGA27763(16);
		ade7763ReadAll(channel);
		ade7763ReadAll(channel);
		ade7763ReadAll(channel);
		for (i = 0; i < 1; i++)
			GetStatus7763();
		GetRstStatus7763();
		GetFrequency7763(VERBOSE_MODE);
		SetTemperature7763(1);
		GetTemperature7763(1);
		GetTemperature7763(1);
		GetTemperature7763(1);
		GetTemperature7763(1);
		GetTemperature7763(1);
		GetTemperature7763(1);
		GetTemperature7763(1);
		GetTemperature7763(1);

		GetVrms7763(1);
		GetVrms7763(1);


		for (;;)
		{
		zmereno.Vrms = GetVrms7763(NON_VERBOSE_MODE);
		DataToFileWrite(konfigurace.mountpoit,konfigurace.fileVrms,zmereno.Vrms);

		zmereno.Irms = GetAutoIrms7763(NON_VERBOSE_MODE);
		DataToFileWrite(konfigurace.mountpoit,konfigurace.fileIrms,zmereno.Irms);

		zmereno.vykon = fakewatt(zmereno.Irms,zmereno.Vrms);
		DataToFileWrite(konfigurace.mountpoit,konfigurace.fileVykon,zmereno.vykon);
		DataNaNic++;

		if (DataNaNic==10)
		{
		i=0;
		zmereno.temperature = GetTemperature7763(NON_VERBOSE_MODE);
		DataToFileWrite(konfigurace.mountpoit,konfigurace.fileTemperature,zmereno.temperature);

		zmereno.frekvency = GetFrequency7763(NON_VERBOSE_MODE);
		DataToFileWrite(konfigurace.mountpoit,konfigurace.fileFrekvency,zmereno.frekvency);

		}



		}
		/*PowerBoardLed(POWERLEDON,POWERLED1);
		PowerBoardLed(POWERLEDOFF,POWERLED1);*/


		/*
		SetScalePGA17763(5);
		printf("Scale 0.5 \n");
		for (a = 0; a < 10; a++) {
			GetIrms7763(0);
		}
		printf("Scale 0.25 \n");
		SetScalePGA17763(25);
		for (a = 0; a < 10; a++) {
			GetIrms7763(0);
		}
		printf("Scale 0.125 \n");
		SetScalePGA17763(125);
		for (a = 0; a < 10; a++) {
			GetIrms7763(0);
		}*/

		//SetScalePGA17763(5);

		//SetScalePGA17763(5);

		for(;;)
GetAutoIrms7763(0);



		mem1 = 0x18;
		mem2 = 0x00;

		for (;;) {
			IrmsCalibrate();
			CLEAN_POLE(MaxBuffSize, MainBuffer);
			MainBuffer[0] = ADRIRMSOS;
			MainBuffer[1] = mem1;
			MainBuffer[2] = mem2;
			ade7763ReadWrite(SPI1, MainBuffer, SPIWRITE, 1);
			//ade7763ReadAll(channel);
		}

		CLEAN_POLE(MaxBuffSize, MainBuffer);
		MainBuffer[0] = 0x0f;
		MainBuffer[1] = 0x00;
		ade7763ReadWrite(SPI1, MainBuffer, SPIWRITE, VERBOSE_MODE);

		CLEAN_POLE(MaxBuffSize, MainBuffer);
		MainBuffer[0] = 0x18;
		MainBuffer[1] = 0x08;
		MainBuffer[2] = 0x13;
		ade7763ReadWrite(SPI1, MainBuffer, SPIWRITE, 0);
		CLEAN_POLE(MaxBuffSize, MainBuffer);

		/*	for(tmp=0; tmp<0xFF;tmp++){
		 CLEAN_POLE(MaxBuffSize,MainBuffer);
		 MainBuffer[0] = 0x18;
		 MainBuffer[1] = 0x08;
		 MainBuffer[2] = tmp;
		 ade7763ReadWrite(SPI1,MainBuffer, SPIWRITE, 0);
		 CLEAN_POLE(MaxBuffSize,MainBuffer);
		 MainBuffer[0] = 0x18;
		 ade7763ReadWrite(SPI1,MainBuffer, SPIREAD, 0);
		 CLEAN_POLE(MaxBuffSize,MainBuffer);
		 MainBuffer[0] = 0x16;
		 ade7763ReadWrite(SPI1,MainBuffer, SPIREAD, 0);
		 }*/
		ade7763ReadAll(channel);
		//delayMicroseconds(20000);
		//	ade7763WriteTest();
		CLEAN_POLE(MaxBuffSize, MainBuffer);
		/*	MainBuffer[0] = 0x1c;
		 MainBuffer[1] = 0x11;
		 ade7763ReadWrite(SPI1,MainBuffer, SPIWRITE, VERBOSE_MODE);

		 CLEAN_POLE(MaxBuffSize,MainBuffer);
		 MainBuffer[0] = 0x1c;
		 MainBuffer[1] = 0x24;
		 ade7763ReadWrite(SPI1,MainBuffer, SPIWRITE, VERBOSE_MODE);
		 ade7763ReadAll(channel);
		 CLEAN_POLE(MaxBuffSize,MainBuffer);
		 MainBuffer[0] = 0x1E;
		 ade7763ReadWrite(SPI1,MainBuffer, SPIREAD, VERBOSE_MODE);
		 CLEAN_POLE(MaxBuffSize,MainBuffer);
		 MainBuffer[0] = 0x1c;
		 MainBuffer[1] = 0x36;
		 ade7763ReadWrite(SPI1,MainBuffer, SPIWRITE, 0);
		 CLEAN_POLE(MaxBuffSize,MainBuffer);
		 MainBuffer[0] = 0x1c;
		 ade7763ReadWrite(SPI1,MainBuffer, SPIREAD, 0);*/

//while(1)
//{
		//for (i=0;i<10;i++)
		//outbuffer[i] = 0x1C;
		//	cnt = wiringPiSPIDataRW(channel, outbuffer, bufsize);
		//	delayMicroseconds(delaytime);
//}
		printf("Done\n");

	}

	return 0;

}

//	bcm2835_spi_setDataMode (BCM2835_SPI_MODE1);

//	pinMode (25, OUTPUT);
//	digitalWrite(25,HIGH);

//  /* Zkusime to vytisknout. */
//  printf("%s", text[0]);

/* Uvolneni pole. */
//for (i=0; i<RADKY; i++) free(text[i]);
//free(text);
//  return(0);
//}

void dataByte(uint8_t data) {
	uint8_t i;

	for (i = 0; i < 8; ++i) {
		switch (i) {
		case 0:
			digitalWrite(LCD_D0, (data & 1));
			data >>= 1;
			break;
		case 1:
			digitalWrite(LCD_D1, (data & 1));
			data >>= 1;
			break;
		case 2:
			digitalWrite(LCD_D2, (data & 1));
			data >>= 1;
			break;
		case 3:
			digitalWrite(LCD_D3, (data & 1));
			data >>= 1;
			break;
		case 4:
			digitalWrite(LCD_D4, (data & 1));
			data >>= 1;
			break;
		case 5:
			digitalWrite(LCD_D5, (data & 1));
			data >>= 1;
			break;
		case 6:
			digitalWrite(LCD_D6, (data & 1));
			data >>= 1;
			break;
		case 7:
			digitalWrite(LCD_D7, (data & 1));
			data >>= 1;
			break;

		}
	}

	/*for (i = 0 ; i < 8 ; ++i)
	 {
	 digitalWrite (i, (data & 1)) ;
	 data >>= 1 ;
	 }*/
}

void putCommand(uint8_t command) {
	digitalWrite(RS, 0);
	digitalWrite(STRB, 1);
	dataByte(command);
	delay (1);
	digitalWrite(STRB, 0);
	delay (1);
}

void lcdPosition(int x, int y) {
	uint8_t l2 = LCD_DGRAM;

	if (y == 1)
		l2 |= 0x40;

	l2 += x;
	putCommand(l2);
}

void lcdPutchar(uint8_t data) {
	digitalWrite(RS, 1);
	digitalWrite(STRB, 1);
	dataByte(data);
	delay (1);
	digitalWrite(STRB, 0);
	delay (1);
}

void lcdPuts(char *string) {
	while (*string)
		lcdPutchar(*string++);
}

void setup(void) {
	uint8_t i;

	if (wiringPiSetup() == -1)
		exit(1);

	for (i = 0; i < 25; ++i) {
		digitalWrite(i, 0);
		pinMode(i, OUTPUT);
	}

	digitalWrite(RS, 0);
	pinMode(RS, OUTPUT);

	digitalWrite(STRB, 1);
	pinMode(STRB, OUTPUT);

	delay (35); // mS
	putCommand(LCD_FUNC | LCD_FUNC_DL | LCD_FUNC_N);
	delay (5);
	putCommand(LCD_FUNC | LCD_FUNC_DL | LCD_FUNC_N);
	delay (5);
	putCommand(LCD_FUNC | LCD_FUNC_DL | LCD_FUNC_N);
	delay (5);

	putCommand(LCD_ON_OFF | LCD_ON_OFF_D);
	delay (2);
	putCommand(LCD_ENTRY | LCD_ENTRY_ID);
	delay (2);
	putCommand(LCD_CDSHIFT | LCD_CDSHIFT_RL);
	delay (2);
	putCommand(LCD_CLEAR);
	delay (5);
}

/**
  * @}
  */

/**
  * @}
  */
